package JdbcPool;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.Properties;
import java.util.logging.Logger;

/**
 * @author zxl
 * @version 1.0
 * @date 2021/10/14 20:46
 * 创建动态代理对象
 * 态代理不需要实现接口,但是需要指定接口类型
 */
public class JdbcPool implements DataSource {

    private static LinkedList<Connection> listConnections = new LinkedList<>();

    static {
        try {
            String driver = "com.mysql.cj.jdbc.Driver";
            String url ="jdbc:mysql://localhost:3306/text?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowMultiQueries=true";
            String username = "root";
            String password = "666666";

            //数据库连接池的初始化连接大小
            int jdbcPoolInitSize = 10;
            //加载数据库驱动
            Class.forName(driver);
            for(int i=0; i<jdbcPoolInitSize; i++) {
                //获取连接
                Connection conn = DriverManager.getConnection(url, username, password);
                System.out.println("获取连接："+conn);
                //将conn连接加入listConnections集合中，此时的listConnections就是一个连接池
                listConnections.add(conn);
            }
        }catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public Connection getConnection(){
        // TODO Auto-generated method stub
        //如果数据库连接池的连接数大于0
        if (listConnections.size()>0) {
            //从listConnections中获取一个连接
            final Connection conn = listConnections.removeFirst();
            System.out.println("数据库连接池的大小为："+listConnections.size());
            //返回Connection的代理，利用代理可以处理一些横切事件
            System.out.println("取出的连接为："+conn);
            //动态代理 参数1：真实对象的类加载器 参数2：真实对象所实现的接口  参数3：实现调用的方法
            return (Connection) Proxy.newProxyInstance(JdbcPool.class.getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    // TODO Auto-generated method stub
                    //如果不是执行关闭操作，则通过反射执行相应方法
                    if (!method.getName().equals("close")) {
                        //执行真实对象中的方法  参数1：对象  参数2：传递的参数
                        Object invoke = method.invoke(conn, args);
                        return invoke;
                    }else {
                        //否则，将conn归还给连接池
                        listConnections.add(conn);
                        System.out.println("归还连接："+conn);
                        System.out.println("连接池大小为："+listConnections.size());
                        return null;
                    }
                }
            });

        }else {
            throw new RuntimeException("对不起，数据库正忙");
        }
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int getLoginTimeout() throws SQLException {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter arg0) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public void setLoginTimeout(int arg0) throws SQLException {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean isWrapperFor(Class<?> arg0) throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public <T> T unwrap(Class<T> arg0) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }



    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }
}
